<?php
/**
 * This file is part of easycrm, created by PhpStorm.
 * Author: LouXin
 * Date: 2015/3/17 11:43
 * File: InstallCommand.php
 */

namespace Icsoc\InstallBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Helper\TableHelper;
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Icsoc\InstallBundle\Composer\PermissionsHandler;

/**
 * Class InstallCommand
 * @package Icsoc\InstallBundle\Command
 */
class InstallCommand extends ContainerAwareCommand
{

    /**
     * Configures the current command.
     */
    protected function configure()
    {
        $this
            ->setName('icsoc:install')
            ->setDescription('初始化安装系统')
        ;
    }

    /**
     * Executes the current command.
     *
     * This method is not abstract because you can use this class
     * as a concrete class. In this case, instead of defining the
     * execute() method, you set the code to execute by passing
     * a Closure to the setCode() method.
     *
     * @param InputInterface $input An InputInterface instance
     * @param OutputInterface $output An OutputInterface instance
     *
     * @return null|int null or 0 if everything went fine, or an error code
     *
     * @throws \LogicException When this abstract method is not implemented
     *
     * @see setCode()
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('<info>Installing Icsoc Application.</info>');
        $output->writeln('');

        $this
            ->checkStep($output)
            ->setUpLogrotate($output)
        ;

        $output->writeln('');
        $output->writeln(
            sprintf(
                '<info>Icsoc Application has been successfully installed in <comment>%s</comment> mode.</info>',
                $input->getOption('env')
            )
        );
        if ('prod' != $input->getOption('env')) {
            $output->writeln(
                '<info>To run application in <comment>prod</comment> mode, ' .
                'please run <comment>cache:clear</comment> command with <comment>--env prod</comment> parameter</info>'
            );
        }
    }

    /**
     * @param OutputInterface $output
     *
     * @return InstallCommand
     * @throws \RuntimeException
     */
    protected function checkStep(OutputInterface $output)
    {
        $output->writeln('<info>Icsoc requirements check:</info>');

        if (!class_exists('IcsocRequirements')) {
            require_once $this->getContainer()->getParameter('kernel.root_dir')
                . DIRECTORY_SEPARATOR
                . 'IcsocRequirements.php';
        }

        $collection = new \IcsocRequirements();

        $this->renderTable($collection->getMandatoryRequirements(), 'Mandatory requirements', $output);
        $this->renderTable($collection->getPhpIniRequirements(), 'PHP settings', $output);
        $this->renderTable($collection->getIcsocRequirements(), 'Icsoc specific requirements', $output);
        $this->renderTable($collection->getRecommendations(), 'Optional recommendations', $output);

        if (count($collection->getFailedRequirements())) {
            throw new \RuntimeException(
                'Some system requirements are not fulfilled. Please check output messages and fix them.'
            );
        }

        $output->writeln('');

        return $this;
    }

    /**
     * 配置日志的logrotate
     * @param OutputInterface $output
     * @return $this
     */
    protected function setUpLogrotate(OutputInterface $output)
    {
        $output->writeln('<info>Setting up logrotate.</info>');

        $fs = $this->getContainer()->get('filesystem');
        $sourcrFile = $this->getContainer()->get('kernel')->getRootDir().'/manage.conf';
        $fs->symlink($sourcrFile, '/etc/logrotate.d/manage.conf');

        return $this;
    }

    /**
     * @param OutputInterface $output
     *
     * @return InstallCommand
     */
    protected function clearCacheStep(OutputInterface $output)
    {
        $output->writeln('<info>Clear all the cache.</info>');

        $container = $this->getContainer();
        $container->get('cache_clearer')->clear($container->get('kernel')->getCacheDir());
        $permission = new PermissionsHandler();
        $permission->setPermissions($container->get('kernel')->getCacheDir());

        $output->writeln('');

        return $this;
    }

    /**
     * Render requirements table
     *
     * @param array           $collection
     * @param string          $header
     * @param OutputInterface $output
     */
    protected function renderTable(array $collection, $header, OutputInterface $output)
    {
        /** @var TableHelper $table */
        $table = $this->getHelperSet()->get('table');

        $table
            ->setHeaders(array('Check  ', $header))
            ->setRows(array());

        /** @var \Requirement $requirement */
        foreach ($collection as $requirement) {
            if ($requirement->isFulfilled()) {
                $table->addRow(array('OK', $requirement->getTestMessage()));
            } else {
                $table->addRow(
                    array(
                        $requirement->isOptional() ? 'WARNING' : 'ERROR',
                        $requirement->getHelpText(),
                    )
                );
            }
        }

        $table->render($output);
    }
}
